package com.android.myapplication.view.media;

import android.app.Service;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import androidx.annotation.Nullable;

public class AudioTrackService extends Service {
    //音频流类型,音乐、铃声、电话等
    private static final int mStreamType = AudioManager.STREAM_MUSIC;
    //指定采样率 （MediaRecoder 的采样率通常是8000Hz AAC的通常是44100Hz。 设置采样率为44100，目前为常用的采样率，官方文档表示这个值可以兼容所有的设置）
    private static final int mSampleRateInHz=44100 ;
    //指定捕获音频的声道数目。在AudioFormat类中指定用于此的常量
    private static final int mChannelConfig= AudioFormat.CHANNEL_CONFIGURATION_MONO; //单声道
    //指定音频量化位数 ,在AudioFormaat类中指定了以下各种可能的常量。通常我们选择ENCODING_PCM_16BIT和ENCODING_PCM_8BIT PCM代表的是脉冲编码调制，它实际上是原始音频样本。
    //因此可以设置每个样本的分辨率为16位或者8位，16位将占用更多的空间和处理能力,表示的音频也更加接近真实。
    private static final int mAudioFormat=AudioFormat.ENCODING_PCM_16BIT;
    //指定缓冲区大小。调用AudioRecord类的getMinBufferSize方法可以获得。
    private int mMinBufferSize;
    //STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到audiotrack中。这个和我们在socket中发送数据一样，
    // 应用层从某个地方获取数据，例如通过编解码得到PCM数据，然后write到audiotrack。
    private static int mMode = AudioTrack.MODE_STREAM;


    public static final String ADUIO_FILE = Environment.getExternalStorageDirectory() + "/my_audio.pcm";

    private AudioTrack mAudioTrack;
    DataInputStream mDis;

    private boolean isPlaying;
    Thread mRecordThread;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new AudioBinder();
    }


    private void initData(){
        mMinBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz,mChannelConfig, mAudioFormat);//计算最小缓冲区
        //注意，按照数字音频的知识，这个算出来的是一秒钟buffer的大小。
        //创建AudioTrack
        mAudioTrack = new AudioTrack(mStreamType, mSampleRateInHz, mChannelConfig,
                mAudioFormat, mMinBufferSize, mMode);
    }

    /**
     * 启动播放线程
     */
    private void startThread() {
        destroyThread();
        if (mRecordThread == null) {
            mRecordThread = new Thread(recordRunnable,"AudioServiceThread");
            mRecordThread.start();
        }
    }
    /**
     * 停止播放
     */
    public void stopPlay() {
        try {
            destroyThread();//销毁线程
            if (mAudioTrack != null) {
                if (mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {//初始化成功
                    mAudioTrack.stop();//停止播放
                }
                if (mAudioTrack != null) {
                    mAudioTrack.release();//释放audioTrack资源
                }
            }
            if (mDis != null) {
                mDis.close();//关闭数据输入流
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 销毁线程方法
     */
    private void destroyThread() {
        try {
            isPlaying = false;
            mRecordThread = null;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            mRecordThread = null;
        }
    }

    /**
     * 增强版Binder，扩展出播放音乐🎵行为
     */
    class AudioBinder extends Binder implements IAudioPlay {

        public AudioBinder(){
            initData();
        }

        /**
         * 播放音乐
         *
         */
        @Override
        public void playMusic() {
            File file = new File(ADUIO_FILE);
            try {
                mDis = new DataInputStream(new FileInputStream(file));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            startThread();

        }

        @Override
        public IBinder asBinder() {
            return this;
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("AAA", "解绑成功");
        // 为什么解绑服务了，音乐还在播放，应该MediaPlay内部是一个服务

        if (mAudioTrack != null) {
            mAudioTrack.stop();

            mAudioTrack.release(); // 释放硬件播放资源
        }
        return super.onUnbind(intent);
    }



    /**
     * 播放线程
     */
    Runnable recordRunnable = new Runnable() {
        @Override
        public void run() {
            try {
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
                byte[] tempBuffer = new byte[mMinBufferSize];
                //判断AudioTrack未初始化，停止播放的时候释放了，状态就为STATE_UNINITIALIZED
                if(mAudioTrack.getState() == mAudioTrack.STATE_UNINITIALIZED){
                    initData();
                }

                isPlaying = true;
                mAudioTrack.play();

                //设置线程的优先级

//                int readCount = tempBuffer.length;
//                Random random = new Random();
//                while (true){
//                    if (!isPlaying){
//                        mAudioTrack.stop();
//                        break;
//                    }
//                    for (int i = 0; i < tempBuffer.length;i++){
//                        tempBuffer[i] += Math.abs(tempBuffer[i] + 20) + 20;
//                    }
//
//                    mAudioTrack.write(tempBuffer, 0, readCount);
//                    AudioView.audioView.setList(tempBuffer);
////                    Thread.sleep(100);
//                }
//
                int readCount = 0;
                mAudioTrack.play();
                while (mDis.available() > 0) {
                    if (!isPlaying){
                        mAudioTrack.stop();
                        break;
                    }
                    readCount= mDis.read(tempBuffer);
                    if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {
                        continue;
                    }
                    if (readCount != AudioTrack.SUCCESS && readCount != AudioTrack.ERROR) {//一边播放一边写入语音数据
                        for (int i = 0; i < readCount; i++){
                            tempBuffer[i] = (byte) (tempBuffer[i] ^ (i & 0xFF));;// < 0 ? tempBuffer[i]  : (byte) -tempBuffer[i];
                        }
                        AudioView.audioView.setList(tempBuffer);
                        mAudioTrack.write(tempBuffer, 0, readCount);
                    }
                }
                mAudioTrack.stop();
                isPlaying = false;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    };
}
